package cn.tinkling.views;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.wb.swt.ResourceManager;
import org.eclipse.wb.swt.SWTResourceManager;

import cn.tinkling.Activator;
import cn.tinkling.youdao.BasicExplain;
import cn.tinkling.youdao.WebExplain;
import cn.tinkling.youdao.YouDaoResult;
import cn.tinkling.youdao.YoudaoDictionary;
import cn.tinkling.youdao.YoudaoDictionary.Callbacks;

/**
 * This sample class demonstrates how to plug-in a new workbench view. The view
 * shows data obtained from the model. The sample creates a dummy model on the
 * fly, but a real implementation would connect to the model available either in
 * this or another plug-in (e.g. the workspace). The view is connected to the
 * model using a content provider.
 * <p>
 * The view uses a label provider to define how model objects should be
 * presented in the view. Each view can present the same model objects using
 * different labels and icons, if needed. Alternatively, a single label provider
 * can be shared between views in order to ensure that objects of the same type
 * are presented in the same way everywhere.
 * <p>
 */

public class YoudaoDictView extends ViewPart {

	/**
	 * The ID of the view as specified by the extension.
	 */
	public static final String ID = "cn.tinkling.views.YoudaoDictView";
	private YoudaoDictionary youdaoDictionary;

	private int historiesIndex = -1;

	private Text text;
	private StyledText resultText;

	private String currentQuery;

	/**
	 * The constructor.
	 */
	public YoudaoDictView() {
	}

	private void initYoudaoDictionary() {
		if (youdaoDictionary == null) {
			youdaoDictionary = new YoudaoDictionary();

			Activator.getDefault().setCallBacks(new Activator.CallBacks() {

				@Override
				public void onStop() {
					youdaoDictionary.shutdown();
					youdaoDictionary = null;
				}
			});
		}
	}

	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {
		parent.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		initYoudaoDictionary();

		onCreareSearcher(parent);
		onCreateResultBody(parent);
	}

	private void onCreareSearcher(Composite parent) {
		GridLayout gl_parent = new GridLayout(1, false);
		gl_parent.verticalSpacing = 8;
		parent.setLayout(gl_parent);

		Composite composite = new Composite(parent, SWT.SEARCH);
		composite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		GridLayout gl_composite = new GridLayout(4, false);
		gl_composite.horizontalSpacing = 8;
		gl_composite.marginWidth = 0;
		gl_composite.marginHeight = 0;
		composite.setLayout(gl_composite);
		composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

		text = new Text(composite, SWT.BORDER);
		text.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 13, SWT.NORMAL));
		text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

		text.addKeyListener(new KeyListener() {

			@Override
			public void keyReleased(KeyEvent e) {
			}

			@Override
			public void keyPressed(KeyEvent e) {
				if (e.keyCode == SWT.CR) {
					onSearch();
				}
			}
		});
		text.addListener(SWT.MouseDoubleClick, new Listener() {

			@Override
			public void handleEvent(Event event) {
				text.setText("");
			}
		});

		Button buttonPre = new Button(composite, SWT.NONE);
		buttonPre.setText("<-");
		buttonPre.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				try {
					String query = youdaoDictionary.getHistories().get(++historiesIndex);
					searchFromHistorie(query);
				} catch (IndexOutOfBoundsException ex) {
					historiesIndex--;
				}
			}
		});

		Button buttonNext = new Button(composite, SWT.NONE);
		buttonNext.setText("->");
		buttonNext.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				try {
					String query = youdaoDictionary.getHistories().get(--historiesIndex);
					searchFromHistorie(query);
				} catch (IndexOutOfBoundsException ex) {
					historiesIndex++;
				}
			}
		});

		Button btnSearch = new Button(composite, SWT.NONE);
		btnSearch.setForeground(SWTResourceManager.getColor(SWT.COLOR_LINK_FOREGROUND));
		btnSearch.setText("\u6709\u9053\u7FFB\u8BD1");
		btnSearch.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				onSearch();
			}
		});
		GridData gd_btnSearch = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
		gd_btnSearch.heightHint = 48;
		gd_btnSearch.widthHint = 150;
		btnSearch.setLayoutData(gd_btnSearch);
		btnSearch.setImage(ResourceManager.getPluginImage("cn.tinkling", "icons/YodaoDict_32.png"));
		btnSearch.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 15, SWT.NORMAL));
	}

	private void onCreateResultBody(Composite parent) {
		final StyledText resultText = new StyledText(parent, SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY);
		resultText.setAlwaysShowScrollBars(false);
		resultText.setBackground(SWTResourceManager.getColor(240, 248, 255));
		resultText.setForeground(SWTResourceManager.getColor(51, 51, 51));
		resultText.setBottomMargin(5);
		resultText.setLeftMargin(15);
		resultText.setRightMargin(15);
		resultText.setTopMargin(5);
		resultText.setFont(SWTResourceManager.getFont("Microsoft YaHei UI", 12, SWT.NORMAL));
		resultText.setWordWrap(true);
		resultText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		this.resultText = resultText;

		Menu menu = new Menu(resultText);
		resultText.setMenu(menu);

		final MenuItem copyMenuItem = new MenuItem(menu, SWT.NONE);
		copyMenuItem.setText("\u590D\u5236");
		copyMenuItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				resultText.copy();
			}
		});

		final MenuItem translateMenuItem = new MenuItem(menu, SWT.NONE);
		translateMenuItem.setText("\u7FFB\u8BD1");
		translateMenuItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (resultText.getSelectionCount() > 0) {
					text.setText(resultText.getSelectionText());
					onSearch();
				}
			}
		});

		menu.addMenuListener(new MenuListener() {

			@Override
			public void menuShown(MenuEvent e) {
				boolean enabled = resultText.getSelectionCount() > 0;
				copyMenuItem.setEnabled(enabled);
				translateMenuItem.setEnabled(enabled);
			}

			@Override
			public void menuHidden(MenuEvent e) {
			}
		});
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		text.setFocus();
		text.setSelection(0, text.getText().length());
	}

	boolean isEmpty(String str) {
		return null == str || str.trim().length() == 0;
	}

	private Callbacks searchCallbacks = new Callbacks() {

		@Override
		public void onHandlQuery(String query, YouDaoResult result) {
			final String cQuery = currentQuery;
			System.out.println("Current Query=" + cQuery);
			System.out.println("Result=" + result);
			if (!cQuery.equals(query) || result == null)
				return;

			if (hasError(result))
				return;

			StringBuilder sb = new StringBuilder();
			sb.append(getHeader(result));

			BasicExplain basicExplain = result.getBasicExplain();
			if (basicExplain != null) {
				sb.append(getExplain(basicExplain.getExplains()));
			} else {
				sb.append(getExplain(result.getTranslation()));
			}

			WebExplain[] webExplains = result.getWebExplains();
			sb.append(getWebExplain(webExplains));

			resultText.setText(sb.toString());

			StyleRange range = new StyleRange();
			range.start = 0;
			range.length = result.getQuery().length() + 4;
			range.fontStyle = SWT.BOLD;
			range.background = SWTResourceManager.getColor(176, 196, 222);
			resultText.setStyleRange(range);
		}

	};

	boolean hasError(YouDaoResult result) {
		if (result.getErrorCode() == YouDaoResult.ERROR_CODE_NONE)
			return false;

		String error;
		switch (result.getErrorCode()) {
			case YouDaoResult.ERROR_CODE_QUERY_TOO_LONG:
				error = "\u8981\u7FFB\u8BD1\u7684\u6587\u672C\u8FC7\u957F";
				break;
			case YouDaoResult.ERROR_CODE_INVALID_KEY:
				error = "\u65E0\u6548\u7684KEY";
				break;
			case YouDaoResult.ERROR_CODE_NO_RESUIT:
				error = "\u65E0\u7FFB\u8BD1\u7ED3\u679C";
				break;
			case YouDaoResult.ERROR_CODE_NONSUPPORT_LANG:
				error = "\u4E0D\u652F\u6301\u7684\u8BED\u8A00\u7C7B\u578B";
				break;
			default:
				error = "\u672A\u77E5\u9519\u8BEF";
				break;
		}
		error = "  " + error + "  ";
		resultText.setText(error);

		StyleRange range = new StyleRange();
		range.start = 0;
		range.length = error.length();
		range.fontStyle = SWT.BOLD;
		range.foreground = SWTResourceManager.getColor(SWT.COLOR_WHITE);
		range.background = SWTResourceManager.getColor(SWT.COLOR_RED);
		resultText.setStyleRange(range);

		return true;
	}

	String getHeader(YouDaoResult result) {
		String query = result.getQuery();
		StringBuilder header = new StringBuilder();

		header.append("  ");
		header.append(query);
		header.append("  ");

		BasicExplain be = result.getBasicExplain();
		if (be != null) {
			header.append('\n');

			String pho = be.getPhonetic();
			if (!isEmpty(pho)) {
				header.append("[");
				header.append(pho);
				header.append("]  ");
			}

			pho = be.getPhoneticUK();
			if (!isEmpty(pho)) {
				header.append("\u82F1[");
				header.append(pho);
				header.append("]  ");
			}

			pho = be.getPhoneticUS();
			if (!isEmpty(pho)) {
				header.append("\u7F8E[");
				header.append(pho);
				header.append("]");
			}
		}

		header.append('\n');
		header.append('\n');

		return header.toString();
	}

	String getPronunciation(YouDaoResult result) {
		return "";
	}

	String getExplain(String[] explains) {
		if (explains == null || explains.length == 0)
			return "";

		StringBuilder explain = new StringBuilder();
		for (String exp : explains) {
			explain.append(exp);
			explain.append('\n');
		}
		// explain.deleteCharAt(explain.length() - 1);
		explain.append('\n');

		return explain.toString();
	}

	String getWebExplain(WebExplain[] webExplains) {
		if (webExplains == null || webExplains.length == 0)
			return "";

		StringBuilder explain = new StringBuilder("\u7F51\u7EDC\u91CA\u4E49:\n");
		String[] values;
		for (WebExplain webExplain : webExplains) {
			explain.append(webExplain.getKey());
			explain.append(" -");
			values = webExplain.getValues();
			for (String v : values) {
				explain.append(' ');
				explain.append(v);
				explain.append(';');
			}

			explain.deleteCharAt(explain.length() - 1);
			explain.append('\n');
		}
		// explain.deleteCharAt(explain.length() - 1);

		return explain.toString();
	}

	private void searchFromHistorie(String historieQuery) {
		historieQuery = historieQuery.trim();
		text.setText(historieQuery);
		currentQuery = historieQuery;
		youdaoDictionary.search(text.getDisplay(), historieQuery, searchCallbacks, true);
	}

	private void onSearch() {

		final String query = text.getText().trim();
		if (isEmpty(query) || (!isEmpty(currentQuery) && currentQuery.equals(query))) {
			return;
		}

		historiesIndex = 0;

		currentQuery = query;
		youdaoDictionary.search(text.getDisplay(), query, searchCallbacks);

	}
}